package org.xx.armory.swing.components;

import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.NavigationFilter;
import javax.swing.text.Position;

import java.awt.event.ActionEvent;

import static org.xx.armory.commons.Validators.greaterThanOrEqual;
import static org.xx.armory.commons.Validators.notNull;

/**
 * 文本框包含前缀和后缀时，控制显示和编辑的导航过滤器。
 */
public class PrefixSuffixNavigationFilter
        extends NavigationFilter {
    private final JTextComponent textComponent;
    private final int prefixLength;
    private final int suffixLength;

    /**
     * 构造导航过滤器。
     *
     * @param textComponent
     *         关联的文本框。
     * @param prefixLength
     *         前缀的长度，最小是0。
     * @param suffixLength
     *         后缀的长度，最小是0。
     * @throws IllegalArgumentException
     *         如果参数{@code textComponent}是{@code null}， 或者参数{@code prefixLength}小于0，或者参数{@code suffixLength}小于0。
     */
    public PrefixSuffixNavigationFilter(
            JTextComponent textComponent,
            int prefixLength,
            int suffixLength
    ) {
        this.textComponent = notNull(textComponent, "textComponent");
        this.prefixLength = greaterThanOrEqual(prefixLength, "prefixLength", 0);
        this.suffixLength = greaterThanOrEqual(suffixLength, "suffixLength", 0);

        final Action deletePrevious = textComponent.getActionMap().get("delete-previous");
        final Action delete = textComponent.getActionMap().get("delete");
        textComponent.getActionMap().put("delete-previous", new AbstractAction() {
            @Override
            public void actionPerformed(
                    ActionEvent event
            ) {
                if (textComponent.getCaretPosition() > prefixLength) {
                    deletePrevious.actionPerformed(event);
                }
            }
        });
        textComponent.setCaretPosition(prefixLength);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDot(
            NavigationFilter.FilterBypass fb,
            int dot,
            Position.Bias bias
    ) {
        super.setDot(fb, restrictDot(dot), bias);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void moveDot(
            NavigationFilter.FilterBypass fb,
            int dot,
            Position.Bias bias
    ) {
        super.moveDot(fb, restrictDot(dot), bias);
    }

    private int restrictDot(
            int dot
    ) {
        final int min = this.prefixLength;
        final int max = this.textComponent.getDocument().getLength() - this.suffixLength;

        if (dot < min) {
            return min;
        } else if (dot > max) {
            return max;
        } else {
            return dot;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getNextVisualPositionFrom(
            JTextComponent text,
            int pos,
            Position.Bias bias,
            int direction,
            Position.Bias[] biasRet
    )
            throws BadLocationException {
        int dot = super.getNextVisualPositionFrom(text, pos, bias, direction, biasRet);

//        final int min = this.prefixLength;
//        final int max = this.textComponent.getDocument().getLength() - this.suffixLength;
//
//        if (dot < min) {
//            dot = min;
//        } else if (dot > max) {
//            dot = max;
//        }

        return dot;
    }
}
